package com.wj.console.freemarkercode.generator;

import java.awt.Desktop;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.wj.console.freemarkercode.util.DateUtil;
import com.wj.console.freemarkercode.util.JDBCHepler;
import com.wj.console.freemarkercode.util.ZipUtil;

import freemarker.template.Template;

/**
 * 描述：代码生成器
 * Created by WJ on 2017/5/1.
 */
public class CodeGenerateUtils {

    private final String AUTHOR = "Wj";
    private final String tableName = "company";
    private final String packageName = "com.wj";
    private final String tableAnnotation = "企业表";
    private final String diskPath = "F://gen//";
    private final String changeTableName = replaceUnderLineAndUpperCase(tableName);
    private Map<String,Object> dataMap = new HashMap<>();

    public static void main(String[] args) throws Exception{
        CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
        codeGenerateUtils.generate();
    }

    public void generate() throws Exception{
        try {
            Connection connection = JDBCHepler.getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            ResultSet resultSet = databaseMetaData.getColumns(null,"%", tableName,"%");
            //读取数据整理
            readData(resultSet);
            //生成Model文件
            generateModelFile();
            //生成vo文件
            generateVOFile();
            //生成Mapper  XML文件
            generateMapperFile();
            //生成Dao文件
            generateDaoFile();
            //生成MapperInterface文件
            generateMapperInterFaceFile();
            //生成服务层接口文件
            generateServiceFile();
            //生成服务实现层文件
            generateServiceImplFile();
            //生成Controller层文件
            generateControllerFile();
            resultSet.close();
            connection.close();
            //压缩文件
            ZipUtil.zip(diskPath+changeTableName+".zip", diskPath+changeTableName);
            //删除文件夹
            deleteFileByWinCom(new File(diskPath +changeTableName));
            //打开文件位置
            Desktop.getDesktop().open(new File(diskPath));
            
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally{
        	
        }
    }
    
    public void readData(ResultSet resultSet) throws Exception{
    	List<ColumnClass> columnClassList = new ArrayList<>();
        ColumnClass columnClass = null;
        while(resultSet.next()){
            //id字段略过
//            if(resultSet.getString("COLUMN_NAME").equals("id")) continue;
            columnClass = new ColumnClass();
            //获取字段名称
            columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
            //获取字段类型
            columnClass.setColumnType(resultSet.getString("TYPE_NAME").toLowerCase());
            //转换字段名称，如 sys_name 变成 SysName
            columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
            //字段在数据库的注释
            columnClass.setColumnComment(resultSet.getString("REMARKS"));
            columnClassList.add(columnClass);
        }
        dataMap.put("model_column",columnClassList);
    }
    
    /**
     * 生成model实体文件
     * @throws Exception
     */
	private void generateModelFile() throws Exception{
        final String suffix = ".java";
        final String path = diskPath +changeTableName+File.separator+"model"+File.separator+ changeTableName + suffix;
        final String filePath = diskPath +changeTableName+File.separator+"model";
        final String templateName = "Model.ftl";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File file = new File(path);
        generateFileByTemplate(templateName,file,dataMap);
    }
	
	/**
	 * 生成VO文件
	 * @throws Exception
	 */
	private void generateVOFile() throws Exception {
		final String suffix = ".java";
        final String path = diskPath +changeTableName+File.separator+"vo"+File.separator+ changeTableName+"Vo" + suffix;
        final String filePath = diskPath +changeTableName+File.separator+"vo";
        final String templateName = "Vo.ftl";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
	}
	
	private void generateDaoFile() throws Exception{
        final String suffix = "Dao.java";
        final String path = diskPath +changeTableName+File.separator+"dao"+File.separator+changeTableName + suffix;
        final String templateName = "DAO.ftl";
        final String filePath = diskPath +changeTableName+File.separator+"dao";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);

    }
	
	private void generateMapperInterFaceFile() throws Exception{
        final String suffix = "Mapper.java";
        final String path = diskPath +changeTableName+File.separator+"mapper"+File.separator+changeTableName + suffix;
        final String templateName = "MapperInterface.ftl";
        final String filePath = diskPath +changeTableName+File.separator+"mapper";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);

    }
	
	private void generateMapperFile() throws Exception{
        final String suffix = "Mapper.xml";
        final String path = diskPath +changeTableName+File.separator+"xml"+File.separator+changeTableName + suffix;
        final String templateName = "Mapper.ftl";
        final String filePath = diskPath +changeTableName+File.separator+"xml";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);

    }

    private void generateServiceFile() throws Exception{
//        final String prefix = "I";
        final String suffix = "Service.java";
        final String path = diskPath +changeTableName+File.separator+"service"+File.separator + changeTableName + suffix;
        final String templateName = "Service.ftl";
        final String filePath = diskPath +changeTableName+File.separator+"service";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }
    
    private void generateServiceImplFile() throws Exception{
        final String suffix = "ServiceImpl.java";
        final String path = diskPath +changeTableName+File.separator+"service"+File.separator+"impl"+File.separator+changeTableName + suffix;
        final String templateName = "ServiceImpl.ftl";
        final String filePath = diskPath +changeTableName+File.separator+"service"+File.separator+"impl";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }
    
    private void generateControllerFile() throws Exception{
        final String suffix = "Controller.java";
        final String path = diskPath +changeTableName+File.separator+"controller"+File.separator+ changeTableName + suffix;
        final String templateName = "Controller.ftl";
        final String filePath = diskPath +changeTableName+File.separator+"controller";
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
        	fileDir.mkdirs();
        }
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }


    private void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("table_name_small",tableName);
        dataMap.put("table_name",changeTableName);
        dataMap.put("author",AUTHOR);
        dataMap.put("date",DateUtil.getDateLong(new Date()));
        dataMap.put("package_name",packageName);
        dataMap.put("table_annotation",tableAnnotation);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
        template.process(dataMap,out);
        out.close();
        fos.close();
    }

    public String replaceUnderLineAndUpperCase(String str){
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while(count!=0){
            int num = sb.indexOf("_",count);
            count = num + 1;
            if(num != -1){
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count , count + 1,ia + "");
            }
        }
        String result = sb.toString().replaceAll("_","");
        return StringUtils.capitalize(result);
    }
    
    
    /**
     * 递归删除目录下的所有文件及子目录下所有文件
     * @param dir 将要删除的文件目录
     * @return boolean Returns 
     * "true" if all deletions were successful.
     *  If a deletion fails, the method stops attempting to
     *  delete and returns "false".
     */
    @SuppressWarnings("unused")
	private static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            //递归删除目录中的子目录下
            for (int i=0; i<children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空，可以删除
        return dir.delete();
    }
    
    /** 
     * 通过递归调用删除一个文件夹及下面的所有文件 
     * @param file 
     */  
    public static void deleteFile(File file){  
        if(file.isFile()){//表示该文件不是文件夹  
            file.delete();  
        }else{  
            //首先得到当前的路径  
            String[] childFilePaths = file.list();  
            for(String childFilePath : childFilePaths){  
                File childFile=new File(file.getAbsolutePath()+"\\"+childFilePath);  
                deleteFile(childFile);  
            }  
            file.delete();  
        }
    }
    
    /** 
     * 通过调用系统命令删除一个文件夹及下面的所有文件 
     * @param file 
     */
    public static void deleteFileByWinCom(File file){  
        Runtime rt = Runtime.getRuntime();  
        String cmd = null;  
        try{  
            if(file.isFile()){  
                cmd = "cmd.exe /c del /q/a/f/s "+file.getAbsolutePath();  
            }else{  
                cmd = "cmd.exe /c rd /s/q "+file.getAbsolutePath();  
            }  
            rt.exec(cmd);  
            System.out.println("成功执行了命令...");  
        }catch(Exception e){  
            System.out.println("调用系统命令失败了...");  
        }  
    }
    

}